package org.jsets.fastboot.eventbus;

import java.util.Objects;
import org.jsets.fastboot.concurrent.AsyncActuator;
import org.jsets.fastboot.util.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 系统默认事件总线 <br>
 * 整合了google guava 包中的 EventBus 和 AsyncEventBus<br>
 * 并进行了易用性封装 <br>
 * 
 * @author wangjie
 *
 */
@Slf4j
public class EventBus {

	private static class SingleHolder {
		private static final EventBus INSTANCE = new EventBus();
	}
	
	public static EventBus getInstance() {
		return SingleHolder.INSTANCE;
	}

	private final DefaultEventBus defaultEventBus;
	private final AsyncEventBus asyncEventBus;

	private EventBus() {
		SubscriberExceptionLoggingHandler exceptionHandler = new SubscriberExceptionLoggingHandler();
		this.defaultEventBus = new DefaultEventBus(exceptionHandler);
		this.asyncEventBus = new AsyncEventBus(AsyncActuator.getDefaultExecutor(), exceptionHandler);

		Boolean registerDeadEventListener = SpringContextHolder.getProperty("event-bus.register-dead-event-listener", Boolean.class);
		if(Objects.isNull(registerDeadEventListener)) {
			registerDeadEventListener = true;
		}
		if(registerDeadEventListener) {
			DeadEventListener deadEventListener = new DeadEventListener();
			this.getDefaultEventBus().register(deadEventListener);
			this.asyncEventBus.register(deadEventListener);
		}
	}

	private DefaultEventBus getDefaultEventBus() {
		return defaultEventBus;
	}

	private AsyncEventBus getAsyncEventBus() {
		return asyncEventBus;
	}

	public static void register(Object object) {
		log.info("register subscriber[{}]", object.getClass());
		getInstance().getDefaultEventBus().register(object);
		getInstance().getAsyncEventBus().register(object);
	}

	public static void unregister(Object object) {
		getInstance().getDefaultEventBus().unregister(object);
		getInstance().getAsyncEventBus().unregister(object);
	}

	public static void post(Object event) {
		getInstance().getDefaultEventBus().post(event);
	}

	public static void asyncPost(Object event) {
		getInstance().getAsyncEventBus().post(event);
	}
	
}